﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using Resn.WhuPub.DAL;
using Resn.WhuPub.DML;

namespace Resn.WhuPub.BLL
{
        /// <summary>
        ///         定义学校/公司的属性和方法
        /// </summary>
        /// <remarks>
        ///         LevelType属性值为本科/高职/高专时，该接口的实例为学校。
        ///         学校下属至少1个校区（BranchCoporate），即主校区，主校区名字不能为空。
        ///         LevelType属性值为公司时，该接口的实例为公司。
        ///         公司下属有且仅有一个分公司（BranchCoporate）。
        ///         该分公司为虚拟分公司，名字为空，但其他联系信息等不能为空，作为公司联系信息。
        /// </remarks>
        public class Corporate : Entity<CorporateModel>
        {
                #region 构造函数

                /// <summary>
                ///         初始化<see cref="Corporate" />学校/公司.
                /// </summary>
                /// <param name="model">学校/公司模型</param>
                public Corporate(CorporateModel model)
                        : base(model)
                {
                }

                #endregion 构造函数

                #region 属性

                #region 基本属性

                /// <summary>
                ///         获取学校/公司的名称
                /// </summary>
                /// <value>
                ///         学校/公司的名称
                /// </value>
                public string Name
                {
                        get { return Model.Name; }
                        set
                        {
                                Model.Name = value;
                                this.NotifyPropertyChanged(i => i.Name);
                        }
                }

                /// <summary>
                ///         获取或设置学校/公司的层次
                /// </summary>
                /// <value>
                ///         学校/公司的层次
                /// </value>
                public CorporateLevel CorporateLevel
                {
                        get { return (CorporateLevel) Enum.Parse(typeof (CorporateLevel), Model.CorporateLevel); }
                        set
                        {
                                Model.CorporateLevel = value.ToString();
                                this.NotifyPropertyChanged(i => i.Name);
                        }
                }

                #endregion 基本属性

                /// <summary>
                ///         获取学校/公司的校区/分公司
                /// </summary>
                /// <value>
                ///         学校/公司的校区/分公司
                /// </value>
                public List<Branch> Branchs
                {
                        get
                        {
                                List<BranchModel> models =
                                        DBStorage.Instance.Select<BranchModel>()
                                                 .Where(i => i.CorporateId == Id)
                                                 .ToList();

                                var result = new List<Branch>();

                                models.ForEach(i => result.Add(new Branch(i)));

                                return result;
                        }
                }


                /// <summary>
                ///         获取学校/公司的主校区/主公司
                /// </summary>
                /// <value>
                ///         学校/公司的主校区/主公司
                /// </value>
                public Branch MainBranch
                {
                        get
                        {
                                switch (CorporateLevel)
                                {
                                        case CorporateLevel.公司:
                                                return Branchs.Single(i => i.Name == Name + Branch.CompanySubName);

                                        default:
                                                return Branchs.Single(i => i.Name == Name + Branch.SchoolSubName);
                                }
                        }
                }

                #endregion 属性

                #region 方法

                /// <summary>
                ///         创建学校/公司
                /// </summary>
                /// <param name="name">名称</param>
                /// <param name="corporateLevel">层次</param>
                /// <returns>
                ///         成功返回创建的对象，失败返回NULL
                /// </returns>
                /// <exception cref="System.InvalidOperationException">该名称学校/公司已存在</exception>
                public static Corporate CreateCorporate(String name, CorporateLevel corporateLevel)
                {
                        Contract.Requires(!string.IsNullOrEmpty(name), "学校/公司名称不能为空");

                        var model = new CorporateModel
                                {
                                        Id = Guid.NewGuid().ToString(),
                                        Name = name,
                                        CorporateLevel = corporateLevel.ToString()
                                };

                        return new Corporate(model);
                }

                /// <summary>
                ///         从EXCEL文件加载学校集合
                /// </summary>
                /// <param name="path">EXCEL文件路径</param>
                /// <returns>
                ///         学校集合
                /// </returns>
                /// <exception cref="System.InvalidOperationException">文件不存在，无法加载</exception>
                public static Dictionary<Corporate, List<Branch>> LoadCorporatesFromExcel(string path)
                {
                        if (!File.Exists(path))
                        {
                                throw new InvalidOperationException("文件不存在，无法加载");
                        }

                        var result = new Dictionary<Corporate, List<Branch>>();

                        using (var fileStream = new FileStream(path, FileMode.Open))
                        {
                                var workBook = new HSSFWorkbook(fileStream);
                                ISheet sheet = workBook.GetSheetAt(0);

                                int rowsCount = sheet.PhysicalNumberOfRows;
                                int columnsCount = sheet.GetRow(0).PhysicalNumberOfCells;

                                if (columnsCount < 8)
                                {
                                        throw new InvalidOperationException("列错误，无法导入");
                                }

                                if (rowsCount < 2)
                                {
                                        throw new InvalidOperationException("行错误，无法导入");
                                }

                                IRow row;
                                string corporateName;
                                string corporateBranchName;
                                string province;
                                string city;
                                string address;
                                string Postcode;
                                string webSite;
                                string corporateLevel;

                                for (int i = 1; i < rowsCount; i++)
                                {
                                        row = sheet.GetRow(i);

                                        corporateName = row.Cells[0].StringCellValue;
                                        corporateBranchName = row.Cells[1].StringCellValue;
                                        province = row.Cells[2].StringCellValue;
                                        city = row.Cells[3].StringCellValue;
                                        address = row.Cells[4].StringCellValue;
                                        Postcode = row.Cells[5].StringCellValue;
                                        webSite = row.Cells[6].StringCellValue;
                                        corporateLevel = row.Cells[7].StringCellValue;

                                        CorporateLevel level;
                                        bool success = Enum.TryParse(corporateLevel, out level);
                                        if (!success)
                                        {
                                                throw new InvalidOperationException(i + "行学校层次错误，无法导入");
                                        }

                                        Corporate corporate;
                                        if (result.Keys.Any(j => j.Name == corporateName))
                                        {
                                                corporate = result.Keys.Single(k => k.Name == corporateName);
                                        }
                                        else
                                        {
                                                corporate = CreateCorporate(corporateName, level);
                                                result.Add(corporate, new List<Branch>());
                                        }

                                        if (string.IsNullOrEmpty(corporateBranchName))
                                        {
                                                corporateBranchName = "本部";
                                        }

                                        if (result[corporate].Any(k => k.Name == corporateBranchName))
                                        {
                                                throw new InvalidOperationException(i + "行校区名称错误，无法导入");
                                        }

                                        Branch corporateBranch = corporate.CreateBranch(corporateBranchName, address,
                                                                                        Postcode, province,
                                                                                        city, webSite);

                                        result[corporate].Add(corporateBranch);
                                }
                        }

                        return result;
                }

                /// <summary>
                ///         添加对象到数据库
                /// </summary>
                /// <exception cref="System.InvalidOperationException">该名称学校/公司已存在</exception>
                public override void Insert()
                {
                        //if (DBCheck.ExistName(CorporateManager.Instance.Corporates, Name))
                        //{
                        //        throw new InvalidOperationException("该名称学校/公司已存在");
                        //}

                        base.Insert();
                }


                /// <summary>
                ///         删除对象从数据库
                /// </summary>
                /// <exception cref="System.InvalidOperationException">该学校/公司下属至少1个校区/分公司，无法删除</exception>
                public override void Delete()
                {
                        var branchs = Branchs;

                        foreach (var branch in branchs)
                        {
                                branch.Delete();
                        }
                        base.Delete();
                }


                /// <summary>
                ///         更新对象到数据库
                /// </summary>
                /// <exception cref="System.InvalidOperationException">该名称学校/公司已存在，无法更新</exception>
                public override void Update()
                {
                        //if (DBCheck.ExistName(CorporateManager.Instance.Corporates, Name))
                        //{
                        //        throw new InvalidOperationException("该名称学校/公司已存在，无法更新");
                        //}
                        base.Update();
                }


                /// <summary>
                ///         创建校区/分公司
                /// </summary>
                /// <param name="name">名称</param>
                /// <param name="address">地址</param>
                /// <param name="postcode">邮编</param>
                /// <param name="province">省份</param>
                /// <param name="city">城市</param>
                /// <param name="webSite">网址</param>
                /// <returns>
                ///         非null:创建成功，返回创建的校区/分公司对象
                ///         null：创建失败
                /// </returns>
                /// <exception cref="System.InvalidOperationException">
                ///         分公司名称必须为空
                ///         or
                ///         校区名称不能为空
                ///         or
                ///         校区名称不能相同
                /// </exception>
                public Branch CreateBranch(string name = "", string address = "",
                                           string postcode = "", string province = "",
                                           string city = "", string webSite = "")
                {
                        switch (CorporateLevel)
                        {
                                case CorporateLevel.公司:
                                        if (!string.IsNullOrEmpty(name))
                                        {
                                                throw new InvalidOperationException("分公司名称必须为空");
                                        }
                                        break;

                                default:
                                        if (string.IsNullOrEmpty(name))
                                        {
                                                throw new InvalidOperationException("校区名称不能为空");
                                        }
                                        break;
                        }

                        List<Branch> corporateBranchs = Branchs;

                        if (DBCheck.ExistName(corporateBranchs, name))
                        {
                                throw new InvalidOperationException("校区名称不能相同");
                        }

                        var model = new BranchModel
                                {
                                        Id = Guid.NewGuid().ToString(),
                                        CorporateId = Id,
                                        Name = name,
                                        Province = province,
                                        City = city,
                                        Address = address,
                                        Postcode = postcode,
                                        Website = webSite
                                };

                        return new Branch(model);
                }

                /// <summary>
                ///         获取指定标识的对象
                /// </summary>
                /// <param name="id">标识</param>
                /// <returns></returns>
                public static Corporate Select(string id)
                {
                        return Select<Corporate>(id);
                }

                #endregion
        }
}